/*
C语言是一个面向过程的语言

而基本上现在的所有现代语言都是面向对象

JAVA 整个系统划分为若干个对象,每个都有自己的数据和方法,然后通过相互调用进行协作完成任务
*/

/*
1. JS数据类型分为两种

基本类型 string boolean null undefined symbol number

引用类型 都是对象 数组、/^$/、Date、Math、Function(更特殊的对象)
*/

console.log(typeof 'ahhh'); // string
console.log(typeof true);  // boolean
console.log(typeof null); // object JS设计的一个意外的BUG
console.log(typeof undefined); // undefined
console.log(typeof Symbol('a'));  // symbol
console.log(typeof 1);   // number

console.log(typeof { name: 'ahhh' });  //object
console.log(typeof [1, 2, 3]);  //object
console.log(typeof /^$/); // object
console.log(typeof new Number(1));  //object
console.log(typeof function (){});  //function

/*
什么是对象?对象和基本数据类型的本质区别是什么?
基本类型是光棍,或则说只是一个值
而对象类型是若干个属性的集合
一切引用类型都是对象

函数也是对象 只是它比较特殊
function为什么这么特殊? 它和其它对象的本质区别是什么?
function本质上来说是可以生产别的对象的,它是一个对象的工厂,所有的对象包括函数本身都是函数生产出来的
*/


// 手工的一个个创建对象
var o = {name:'ahhh', age: 10};
var o1 = {name:'ahhh2', age: 11};

// 为了加快生产对象的速度,就有了函数,函数可以用来批量的生产对象(new)
function Person(name,age){
  this.name = name;
  this.age = age;
}

var ahhh1 = new Person('ahhh1', 10);
var ahhh2 = new Person('ahhh2', 10);

// 我们可以将对象的属性分成两种:
// + 有些属性是每个对象所特有的,都不一样(通过new 构造函数传参
// + 另一种是所有Person都一样的(通过prototype
// 保证了灵活,节约了内存

/** prototype */
//只有函数才有 prototype原型
Person.prototype.eat = function () {console.log('吃饭')};

/** new 模拟*/
function _new(clazz, ...args) {
  let obj = {};
  obj.__proto__ = clazz.prototype; // 关联构造函数的原形
  clazz.call(obj, ...args); // 给实例私有属性赋值
  return obj;
}
var zhangsan = _new(Person, 'zhangsan', 10);
console.log(zhangsan); // Person { name: 'zhangsan', age: 10 }
zhangsan.__proto__.eat(); // 吃饭
/** __proto__ 可以省略 称之为 隐式原形*/
zhangsan.eat(); // 吃饭

/** 总结
每个对象都有一个proto属性,指向创建该对象的函数的prototype
Object.prototype__proto__指向的是null

通过new来调用一个函数,这个函数就成为了构造函数,构造函数里可以对其实例对象的私有属性赋值
每个函数会有一个prototype属性,此原型对象上存放所有实例的公有属性
若new的构造函数自己返回引用值,则以自己返回的为主,否则 返回创建的实例
*/
